home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr07 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / basic.c < prev    next >
C/C++ Source or Header  |  1993-03-30  |  36KB  |  2,179 lines

  1. /*    Copyright (C) 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17.  
  18. #include <ctype.h>
  19. #include "sysdef.h"
  20. #include "global.h"
  21. #include "basic.h"
  22. #include "cmd.h"
  23. #include "regions.h"
  24. #include "window.h"
  25. #include "io-term.h"
  26. #include "io-generic.h"
  27. #include "io-abstract.h"
  28. #include "io-utils.h"
  29. #include "io-curses.h"
  30. #include "ref.h"
  31. #include "format.h"
  32. #include "lists.h"
  33. #include "io-edit.h"
  34. #include "eval.h"
  35. #include "byte-compile.h"
  36.  
  37.  
  38. /* Used by motion commands. */
  39. const int colmagic[] = {0, 0, 1, -1, 1, -1, 1, -1, 0};
  40. const int rowmagic[] = {-1, 1, 0, 0, -1, -1, 1, 1, 0};
  41.  
  42. char * motion_name[] =  
  43. {
  44.   "up",
  45.   "down",
  46.   "right",
  47.   "left",
  48.   "up right",
  49.   "up left",
  50.   "down right",
  51.   "down left",
  52.   "no motion"
  53. };
  54.  
  55.  
  56. /* This table ought to be a user parameter. */
  57. enum motion_magic complementary_motion[] = 
  58. {
  59.   magic_right,
  60.   magic_right,
  61.   magic_down,
  62.   magic_down,
  63.   magic_right,
  64.   magic_right,
  65.   magic_right,
  66.   magic_right,
  67.   magic_no_motion,
  68. };
  69.  
  70. enum motion_magic opposite_motion[] = 
  71. {
  72.   magic_down,
  73.   magic_up,
  74.   magic_left,
  75.   magic_right,
  76.   magic_down_left,
  77.   magic_down_right,
  78.   magic_up_left,
  79.   magic_up_right,
  80.   magic_no_motion,
  81. };
  82.  
  83.  
  84. /* Indexed by MAGIC + 1 */
  85. const int boundrymagic[3] = { MIN_ROW, NON_ROW, MAX_ROW };
  86.  
  87.  
  88.  
  89.  
  90. /* A very basic command. */
  91.  
  92. #ifdef __STDC__
  93. void
  94. noop (void)
  95. #else
  96. void
  97. noop ()
  98. #endif
  99. {}
  100.  
  101.  
  102.  
  103. /* Commands that inser/delete rows/columns. */
  104.  
  105. #ifdef __STDC__
  106. void
  107. insert_row (int repeat)
  108. #else
  109. void
  110. insert_row (repeat)
  111.      int repeat;
  112. #endif
  113. {
  114.   struct rng from;
  115.   struct rng to;
  116.   if ((repeat > (MAX_ROW - curow)) || (repeat < 0))
  117.     {
  118.       io_error_msg ("insert-row: prefix argument out of range.");
  119.       return;
  120.     }
  121.   from.lc = MIN_COL;
  122.   from.hc = MAX_COL;
  123.   from.lr = curow;
  124.   from.hr = MAX_ROW - repeat;
  125.   to.lc = MIN_COL;
  126.   to.hc = MIN_COL;
  127.   to.lr = curow + repeat;
  128.   to.hr = curow + repeat;
  129.   move_region (&from, &to);
  130. }
  131.  
  132. #ifdef __STDC__
  133. void
  134. insert_col (int repeat)
  135. #else
  136. void
  137. insert_col (repeat)
  138.      int repeat;
  139. #endif
  140. {
  141.   struct rng from;
  142.   struct rng to;
  143.   if ((repeat > (MAX_COL - cucol)) || (repeat < 0))
  144.     {
  145.       io_error_msg ("insert-col: prefix argument out of range.");
  146.       return;
  147.     }
  148.   from.lr = MIN_ROW;
  149.   from.hr = MAX_ROW;
  150.   from.lc = cucol;
  151.   from.hc = MAX_COL - repeat;
  152.   to.lr = MIN_ROW;
  153.   to.hr = MIN_ROW;
  154.   to.lc = cucol + repeat;
  155.   to.hc = cucol + repeat;
  156.   move_region (&from, &to);
  157. }
  158.  
  159. #ifdef __STDC__
  160. void
  161. delete_row (int repeat)
  162. #else
  163. void
  164. delete_row (repeat)
  165.      int repeat;
  166. #endif
  167. {
  168.   struct rng from;
  169.   struct rng to;
  170.   if ((repeat < 0) || (repeat > (MAX_ROW - curow + 1)))
  171.     {
  172.       io_error_msg ("delete-row: prefix argument out of range.");
  173.       return;
  174.     }
  175.   from.lc = MIN_COL;
  176.   from.hc = MAX_COL;
  177.   from.lr = curow + repeat;
  178.   from.hr = MAX_ROW;
  179.   to.lc = MIN_COL;
  180.   to.hc = MIN_COL;
  181.   to.lr = curow;
  182.   to.hr = curow;
  183.   move_region (&from, &to);
  184. }
  185.  
  186. #ifdef __STDC__
  187. void
  188. delete_col (int repeat)
  189. #else
  190. void
  191. delete_col (repeat)
  192.      int repeat;
  193. #endif
  194. {
  195.   struct rng from;
  196.   struct rng to;
  197.   if ((repeat < 0) || (repeat > (MAX_COL - cucol + 1)))
  198.     {
  199.       io_error_msg ("delete-col: prefix argument out of range.");
  200.       return;
  201.     }
  202.   from.lr = MIN_ROW;
  203.   from.hr = MAX_ROW;
  204.   from.lc = cucol + repeat;
  205.   from.hc = MAX_COL;
  206.   to.lr = MIN_ROW;
  207.   to.hr = MIN_ROW;
  208.   to.lc = cucol;
  209.   to.hc = cucol;
  210.   move_region (&from, &to);
  211. }
  212.  
  213.  
  214.  
  215. /* Front end to the window functions. */
  216.  
  217. #ifdef __STDC__
  218. void 
  219. open_window (char *text)
  220. #else
  221. void 
  222. open_window (text)
  223.      char *text;
  224. #endif
  225. {
  226.   int hv;
  227.   int where;
  228.  
  229.   while (*text == ' ')
  230.     text++;
  231.  
  232.   if (*text == 'h' || *text == 'H')
  233.     hv = 0;
  234.   else if (*text == 'v' || *text == 'V')
  235.     hv = 1;
  236.   else
  237.     {
  238.       io_error_msg ("Open 'h'orizontal or 'v'ertical window, not '%s'", text);
  239.       return;
  240.     }
  241.   where = atoi (text + 1);
  242.   while (isspace (*text))
  243.     ++text;
  244.   while (isalnum (*text))
  245.     ++text;
  246.   while (isspace (*text))
  247.     ++text;
  248.   if (*text == '%')
  249.     {
  250.       where *= (hv
  251.         ? (cwin->numr + (cwin->lh_wid ? label_rows : 0))
  252.         : (cwin->numc + cwin->lh_wid));
  253.       where /= 100;
  254.     }
  255.   io_win_open (hv, where);
  256. }
  257.  
  258. #ifdef __STDC__
  259. void
  260. hsplit_window (void)
  261. #else
  262. void
  263. hsplit_window ()
  264. #endif
  265. {
  266.   open_window ("h50%");
  267. }
  268.  
  269.  
  270. #ifdef __STDC__
  271. void
  272. vsplit_window (void)
  273. #else
  274. void
  275. vsplit_window ()
  276. #endif
  277. {
  278.   open_window ("v50%");
  279. }
  280.  
  281.  
  282. #ifdef __STDC__
  283. void 
  284. close_window (char *text)
  285. #else
  286. void 
  287. close_window (text)
  288.      char *text;
  289. #endif
  290. {
  291.   int num;
  292.  
  293.   num = atoi (text) - 1;
  294.  
  295.   if (num < 0 || num >= nwin)
  296.     {
  297.       io_error_msg ("Window %num?", text);
  298.       return;
  299.     }
  300.   if (nwin == 1)
  301.     {
  302.       io_error_msg ("You can't close the last window!");
  303.       return;
  304.     }
  305.   io_win_close (&wins[num]);
  306. }
  307.  
  308. #ifdef __STDC__
  309. void 
  310. delete_window (void)
  311. #else
  312. void 
  313. delete_window ()
  314. #endif
  315. {
  316.   io_win_close (cwin);
  317. }
  318.  
  319. #ifdef __STDC__
  320. void
  321. delete_other_windows (void)
  322. #else
  323. void
  324. delete_other_windows ()
  325. #endif
  326. {
  327.   if (nwin > 1)
  328.     {
  329.       CELLREF r = curow;
  330.       CELLREF c = cucol;
  331.       while (nwin > 1)
  332.     io_win_close (cwin);
  333.       io_move_cell_cursor (r, c);
  334.     }
  335. }
  336.  
  337. #ifdef __STDC__
  338. void 
  339. nicely_goto_window (int n)
  340. #else
  341. void 
  342. nicely_goto_window (n)
  343.      int n;
  344. #endif
  345. {
  346.   if (input_active)
  347.     {
  348.       io_cellize_cursor ();
  349.       window_after_input = n;
  350.       input_active = 0;
  351.       the_cmd_frame->top_keymap = map_id ("main");
  352.       return;
  353.     }
  354.   else
  355.     {
  356.       if ((window_after_input >= 0)
  357.       && ((window_after_input % nwin) == n))
  358.     {
  359.       io_inputize_cursor ();
  360.       window_after_input = -1;
  361.       input_active = 1;
  362.       the_cmd_frame->top_keymap =
  363.         map_id (the_cmd_frame->cmd
  364.             ? the_cmd_arg.style->keymap
  365.             : "main");
  366.     }
  367.       else
  368.     io_set_cwin (&wins[n]);
  369.     }
  370. }
  371.  
  372. #ifdef __STDC__
  373. void
  374. goto_minibuffer (void)
  375. #else
  376. void
  377. goto_minibuffer ()
  378. #endif
  379. {
  380.   if (window_after_input < 0)
  381.     {
  382.       if (!input_active)
  383.     io_error_msg ("Minibuffer not active.");
  384.     }
  385.   else
  386.     nicely_goto_window ((window_after_input % nwin));
  387. }
  388.  
  389.  
  390. #ifdef __STDC__
  391. void
  392. goto_window (char *text)
  393. #else
  394. void
  395. goto_window (text)
  396.      char *text;
  397. #endif
  398. {
  399.   int n;
  400.   n = atoi (text) - 1;
  401.   if (n < 0 || n > nwin)
  402.     {
  403.       io_error_msg ("Window %s doesn't exist.", text);
  404.       return;
  405.     }
  406.   else
  407.     nicely_goto_window (n);
  408. }
  409.  
  410.  
  411. #ifdef __STDC__
  412. void 
  413. other_window (void)
  414. #else
  415. void 
  416. other_window ()
  417. #endif
  418. {
  419.   int n = cwin - wins;
  420.   if (!input_active)
  421.     n = (n + 1) % nwin;
  422.   nicely_goto_window (n);
  423. }
  424.  
  425. #ifdef __STDC__
  426. int
  427. set_window_option (int set_opt, char *text)
  428. #else
  429. int
  430. set_window_option (set_opt, text)
  431.      int set_opt;
  432.      char *text;
  433. #endif
  434. {
  435.   int n;
  436.   int stat;
  437.   static struct opt
  438.     {
  439.       char *text;
  440.       int bits;
  441.     }
  442.   opts[] =
  443.   {
  444.     {
  445.       "reverse", WIN_EDGE_REV
  446.     }
  447.     ,
  448.     {
  449.       "standout", WIN_EDGE_REV
  450.     }
  451.     ,
  452.     {
  453.       "page", WIN_PAG_HZ | WIN_PAG_VT
  454.     }
  455.     ,
  456.     {
  457.       "pageh", WIN_PAG_HZ
  458.     }
  459.     ,
  460.     {
  461.       "pagev", WIN_PAG_VT
  462.     }
  463.     ,
  464.     {
  465.       "lockh", WIN_LCK_HZ
  466.     }
  467.     ,
  468.     {
  469.       "lockv", WIN_LCK_VT
  470.     }
  471.     ,
  472.     {
  473.       "edges", WIN_EDGES
  474.     }
  475.   };
  476.   if ((stat = (!strincmp (text, "status", 6) && isspace (text[6])))
  477.       || (!strincmp (text, "input", 5) && isspace (text[5])))
  478.     {
  479.       int n = set_opt ? atoi (text + 6 + stat) : 0;    /* A little pun. */
  480.       int new_inp = stat ? user_input : n;
  481.       int new_stat = stat ? n : user_status;
  482.       io_set_input_status (new_inp, new_stat, 1);
  483.     }
  484.   else if (!strincmp (text, "link", 4))
  485.     {
  486.       if (set_opt)
  487.     {
  488.       n = atoi (text + 4) - 1;
  489.       if (n < 0 || n > nwin)
  490.         io_error_msg ("Can't '%s': window # out of range", text);
  491.       else
  492.         cwin->link = n;
  493.     }
  494.       else
  495.     cwin->link = -1;
  496.     }
  497.   else if (set_opt && !stricmp (text, "unlink"))
  498.     cwin->link = -1;
  499.   else if (set_opt && !strincmp (text, "row ", 4))
  500.     {
  501.       text += 4;
  502.       curow = astol (&text);
  503.     }
  504.   else if (set_opt && !strincmp (text, "col ", 4))
  505.     {
  506.       text += 4;
  507.       cucol = astol (&text);
  508.     }
  509.   else
  510.     {
  511.       for (n = 0; n < sizeof (opts) / sizeof (struct opt); n++)
  512.     if (!stricmp (text, opts[n].text))
  513.       {
  514.         if (set_opt)
  515.           cwin->flags |= opts[n].bits;
  516.         else
  517.           cwin->flags &= ~opts[n].bits;
  518.         break;
  519.       }
  520.  
  521.       if (n == sizeof (opts) / sizeof (struct opt))
  522.       return 0;
  523.     }
  524.   return 1;
  525. }
  526.  
  527. #ifdef __STDC__
  528. void
  529. show_window_options (void)
  530. #else
  531. void
  532. show_window_options ()
  533. #endif
  534. {
  535.   int n;
  536.  
  537.   cwin->win_curow = curow;
  538.   cwin->win_cucol = cucol;
  539.   if (user_status)
  540.     io_text_line ("Status line at %d", user_status);
  541.   else
  542.     io_text_line ("Status line disabled.");
  543.   io_text_line ("");
  544.   for (n = 0; n < nwin; n++)
  545.     {
  546.       int flags = wins[n].flags;
  547.       io_text_line ("Window #%d showing %s, with cursor at %s",
  548.             n + 1,
  549.             range_name (&wins[n].screen),
  550.             cell_name (wins[n].win_curow, wins[n].win_cucol));
  551.       io_text_line ("   Options:  %sedges (%sreverse)%s%s%s%s",
  552.             flags & WIN_EDGES ? "" : "no",
  553.             flags & WIN_EDGE_REV ? "" : "no",
  554.             flags & WIN_PAG_HZ ? ", pageh" : "",
  555.             flags & WIN_PAG_VT ? ", pagev" : "",
  556.             flags & WIN_LCK_HZ ? ", lockh" : "",
  557.             flags & WIN_LCK_VT ? ", lockv" : "");
  558.       if (wins[n].link != -1)
  559.     io_text_line ("Linked to window %d", wins[n].link + 1);
  560.     }
  561. }
  562.  
  563. #ifdef __STDC__
  564. void
  565. recenter_window (void)
  566. #else
  567. void
  568. recenter_window ()
  569. #endif
  570. {
  571.   io_recenter_cur_win ();
  572. }
  573.  
  574.  
  575.  
  576. /* Trivial front-end commands. */
  577.  
  578.  
  579. #ifdef __STDC__
  580. void
  581. suspend_oleo (void)
  582. #else
  583. void
  584. suspend_oleo ()
  585. #endif
  586. {
  587.   if (using_curses)
  588.     {
  589.       stop_curses ();
  590.       kill (getpid (), SIGSTOP);
  591.     }
  592. }
  593.  
  594. #ifdef __STDC__
  595. void
  596. recalculate (int all)
  597. #else
  598. void
  599. recalculate (all)
  600.      int all;
  601. #endif
  602. {
  603.   current_cycle++;
  604.   if (all)
  605.     {
  606.       CELLREF row;
  607.       CELLREF col;
  608.       struct rng all;
  609.       all.lr = MIN_ROW;
  610.       all.hr = MAX_ROW;
  611.       all.lc = MIN_COL;
  612.       all.hc = MAX_COL;
  613.       find_cells_in_range (&all);
  614.       while (next_row_col_in_range (&row, &col))
  615.     push_cell (row, col);
  616.     }
  617.   while (eval_next_cell ())
  618.     ;
  619. }
  620.  
  621.  
  622. #ifdef __STDC__
  623. void
  624. kill_oleo (void)
  625. #else
  626. void
  627. kill_oleo ()
  628. #endif
  629. {
  630.   io_close_display ();
  631.   exit (0);
  632. }
  633.  
  634.  
  635. #ifdef __STDC__
  636. void
  637. kill_all_cmd (void)
  638. #else
  639. void
  640. kill_all_cmd ()
  641. #endif
  642. {
  643.   clear_spreadsheet ();
  644.   io_repaint ();
  645. }
  646.  
  647. #ifdef __STDC__
  648. void
  649. redraw_screen (void)
  650. #else
  651. void
  652. redraw_screen ()
  653. #endif
  654. {
  655.   io_repaint ();
  656. }
  657.  
  658.  
  659.  
  660. /* Motion commands. */
  661.  
  662. #ifdef __STDC__
  663. void
  664. shift_cell_cursor (int dir, int repeat)
  665. #else
  666. void
  667. shift_cell_cursor (dir, repeat)
  668.      int dir;
  669.      int repeat;
  670. #endif
  671. {
  672.   io_shift_cell_cursor (dir, repeat);
  673. }
  674.  
  675.  
  676. #ifdef __STDC__
  677. void
  678. scroll_cell_cursor (int dir, int repeat)
  679. #else
  680. void
  681. scroll_cell_cursor (dir, repeat)
  682.      int dir;
  683.      int repeat;
  684. #endif
  685. {
  686.   io_scroll_cell_cursor (dir, repeat);
  687. }
  688.  
  689.  
  690.  
  691. #ifdef __STDC__
  692. void
  693. goto_region (struct rng *r)
  694. #else
  695. void
  696. goto_region (r)
  697.      struct rng *r;
  698. #endif
  699. {
  700.   (void) io_move_cell_cursor (r->lr, r->lc);
  701.  
  702.   if (r->hr != r->lr || r->hc != r->lc)
  703.     {
  704.       mkrow = r->hr;
  705.       mkcol = r->hc;
  706.     }
  707.   else if (mkrow != NON_ROW)
  708.     mkrow = NON_ROW;
  709.   io_update_status ();
  710. }
  711.  
  712. #ifdef __STDC__
  713. void
  714. goto_cell (struct rng * rng)
  715. #else
  716. void
  717. goto_cell (rng)
  718.      struct rng * rng;
  719. #endif
  720. {
  721.   rng->hr = mkrow;
  722.   rng->hc = mkcol;
  723.   goto_region (rng);
  724. }
  725.  
  726. #ifdef __STDC__
  727. void
  728. exchange_point_and_mark (int clrmk)
  729. #else
  730. void
  731. exchange_point_and_mark (clrmk)
  732.      int clrmk;
  733. #endif
  734. {
  735.   struct rng rng;
  736.   if (clrmk)
  737.     {
  738.       rng.lr = curow;
  739.       rng.lc = cucol;
  740.       rng.hr = NON_ROW;
  741.       rng.hc = NON_COL;
  742.       goto_region (&rng);
  743.     }
  744.   else if (mkrow != NON_ROW)
  745.     {
  746.       rng.lr = mkrow;
  747.       rng.lc = mkcol;
  748.       rng.hr = curow;
  749.       rng.hc = cucol;
  750.       goto_region (&rng);
  751.     }
  752. }
  753.  
  754. #ifdef __STDC__
  755. static CELLREF
  756. first_filled_col (CELLREF row)
  757. #else
  758. static CELLREF
  759. first_filled_col (row)
  760.      CELLREF row;
  761. #endif
  762. {
  763.   struct rng rng;
  764.   CELLREF r;
  765.   CELLREF c;
  766.   rng.lr = row;
  767.   rng.hr = row;
  768.   rng.lc = MIN_COL;
  769.   rng.hc = MAX_COL;
  770.   find_cells_in_range (&rng);
  771.   while (1)
  772.     {
  773.       CELL * cp;
  774.       cp = next_row_col_in_range (&r, &c);
  775.       if (!cp)
  776.     break;
  777.       if (GET_TYP(cp))
  778.     {
  779.       no_more_cells ();
  780.       return c;
  781.     }
  782.     }
  783.   return NON_COL;
  784. }
  785.  
  786. #ifdef __STDC__
  787. static CELLREF
  788. last_filled_col (CELLREF row)
  789. #else
  790. static CELLREF
  791. last_filled_col (row)
  792.      CELLREF row;
  793. #endif
  794. {
  795.   struct rng rng;
  796.   CELLREF r;
  797.   CELLREF c;
  798.   CELLREF bestc = MIN_COL;
  799.   rng.lr = row;
  800.   rng.hr = row;
  801.   rng.lc = MIN_COL;
  802.   rng.hc = MAX_COL;
  803.   find_cells_in_range (&rng);
  804.   while (1)
  805.     {
  806.       CELL * cp;
  807.       cp = next_row_col_in_range (&r, &c);
  808.       if (!cp)
  809.     break;
  810.       if (GET_TYP(cp))
  811.     bestc = c;
  812.     }
  813.   return bestc;
  814. }
  815.  
  816. #ifdef __STDC__
  817. static CELLREF
  818. first_filled_row (CELLREF col)
  819. #else
  820. static CELLREF
  821. first_filled_row (col)
  822.      CELLREF col;
  823. #endif
  824. {
  825.   struct rng rng;
  826.   CELLREF r;
  827.   CELLREF c;
  828.   CELL * cp;
  829.   rng.lr = MIN_ROW;
  830.   rng.hr = MAX_ROW;
  831.   rng.lc = col;
  832.   rng.hc = col;
  833.   find_cells_in_range (&rng);
  834.   while (1)
  835.     {
  836.       cp = next_row_col_in_range (&r, &c);
  837.       if (!cp)
  838.     break;
  839.       if (GET_TYP(cp))
  840.     {
  841.       no_more_cells ();
  842.       return r;
  843.     }
  844.     }
  845.   return NON_ROW;
  846. }
  847.  
  848. #ifdef __STDC__
  849. static CELLREF
  850. last_filled_row (CELLREF col)
  851. #else
  852. static CELLREF
  853. last_filled_row (col)
  854.      CELLREF col;
  855. #endif
  856. {
  857.   struct rng rng;
  858.   CELLREF r;
  859.   CELLREF c;
  860.   CELLREF bestr = MIN_ROW;
  861.   CELL * cp;
  862.   rng.lr = MIN_ROW;
  863.   rng.hr = MAX_ROW;
  864.   rng.lc = col;
  865.   rng.hc = col;
  866.   find_cells_in_range (&rng);
  867.   while (1)
  868.     {
  869.       cp = next_row_col_in_range (&r, &c);
  870.       if (!cp)
  871.     break;
  872.       if (GET_TYP(cp))
  873.     bestr = r;
  874.     }
  875.   return bestr;
  876. }
  877.  
  878. #ifdef __STDC__
  879. static CELLREF
  880. max_filled_row (void)
  881. #else
  882. static CELLREF
  883. max_filled_row ()
  884. #endif
  885. {
  886.   CELLREF max_r = highest_row ();
  887.   while (max_r != MIN_ROW)
  888.     {
  889.       CELLREF c = first_filled_col (max_r);
  890.       if (c != NON_COL)
  891.     break;
  892.       --max_r;
  893.     }
  894.   return max_r;
  895. }
  896.  
  897.  
  898. #ifdef __STDC__
  899. static CELLREF
  900. max_filled_col (void)
  901. #else
  902. static CELLREF
  903. max_filled_col ()
  904. #endif
  905. {
  906.   CELLREF max_c = highest_col ();
  907.   while (max_c != MIN_COL)
  908.     {
  909.       CELLREF r = first_filled_row (max_c);
  910.       if (r != NON_COL)
  911.     break;
  912.       --max_c;
  913.     }
  914.   return max_c;
  915. }
  916.  
  917. #ifdef __STDC__
  918. static void 
  919. mk_for_extreme (struct rng * rng)
  920. #else
  921. static void 
  922. mk_for_extreme (rng)
  923.      struct rng * rng;
  924. #endif
  925. {
  926.   if (mkrow != NON_ROW)
  927.     {
  928.       rng->hr = mkrow;
  929.       rng->hc = mkcol;
  930.     }
  931.   else
  932.     {
  933.       rng->hc = cucol;
  934.       rng->hr = curow;
  935.     }
  936. }
  937.  
  938. #ifdef __STDC__
  939. void
  940. upper_left (void)
  941. #else
  942. void
  943. upper_left ()
  944. #endif
  945. {
  946.   struct rng rng;
  947.   rng.lr = MIN_ROW;
  948.   rng.lc = MIN_COL;
  949.   mk_for_extreme (&rng);
  950.   goto_region (&rng);
  951. }
  952.  
  953. #ifdef __STDC__
  954. void
  955. lower_left (void)
  956. #else
  957. void
  958. lower_left ()
  959. #endif
  960. {
  961.   struct rng rng;
  962.   rng.lr = max_filled_row ();
  963.   rng.lc = MIN_COL;
  964.   mk_for_extreme (&rng);
  965.   goto_region (&rng);
  966. }
  967.  
  968. #ifdef __STDC__
  969. void
  970. upper_right (void)
  971. #else
  972. void
  973. upper_right ()
  974. #endif
  975. {
  976.   struct rng rng;
  977.   rng.lr = MIN_ROW;
  978.   rng.lc = max_filled_col ();
  979.   mk_for_extreme (&rng);
  980.   goto_region (&rng);
  981. }
  982.  
  983. #ifdef __STDC__
  984. void
  985. lower_right (void)
  986. #else
  987. void
  988. lower_right ()
  989. #endif
  990. {
  991.   struct rng rng;
  992.   rng.lr = max_filled_row ();
  993.   rng.lc = max_filled_col ();
  994.   mk_for_extreme (&rng);
  995.   goto_region (&rng);
  996. }
  997.  
  998. #ifdef __STDC__
  999. void
  1000. mark_cell_cmd (int popmk)
  1001. #else
  1002. void
  1003. mark_cell_cmd (popmk)
  1004.      int popmk;
  1005. #endif
  1006. {
  1007.   if (popmk)
  1008.     {
  1009.       if (mkrow != NON_ROW)
  1010.     {
  1011.       struct rng rng;
  1012.       rng.lr = mkrow;
  1013.       rng.lc = mkcol;
  1014.       rng.hr = NON_ROW;
  1015.       rng.hc = NON_COL;
  1016.       goto_region (&rng);
  1017.     }
  1018.     }
  1019.   else
  1020.     {
  1021.       mkrow = curow;
  1022.       mkcol = cucol;
  1023.       io_update_status ();
  1024.     }
  1025. }
  1026.  
  1027. #ifdef __STDC__
  1028. void
  1029. unmark_cmd (void)
  1030. #else
  1031. void
  1032. unmark_cmd ()
  1033. #endif
  1034. {
  1035.   mkrow = NON_ROW;
  1036.   mkcol = NON_COL;
  1037.   io_update_status ();
  1038. }
  1039.  
  1040.  
  1041. /* This is a bit kludgey. Input line editting has its own event loop (grr!),
  1042.  * and all of its state is private.  These mouse commands can't entirely
  1043.  * handle it when the target is in the input line.  In that case, they
  1044.  * save the decoded mouse event where io_get_line can pick it up:
  1045.  */
  1046. struct mouse_event last_mouse_event;
  1047.  
  1048. #ifdef __STDC__
  1049. void
  1050. do_mouse_goto (void)
  1051. #else
  1052. void
  1053. do_mouse_goto ()
  1054. #endif
  1055. {
  1056.   if (!last_mouse_event.downp)
  1057.     return;
  1058.   if (last_mouse_event.location >= 0 && last_mouse_event.downp)
  1059.     {
  1060.       if (input_active)
  1061.     {
  1062.       io_cellize_cursor ();
  1063.       window_after_input = last_mouse_event.location;
  1064.       input_active = 0;
  1065.       the_cmd_frame->top_keymap = map_id ("main");
  1066.     }
  1067.       io_set_cwin (&wins[last_mouse_event.location]);
  1068.       io_move_cell_cursor (last_mouse_event.r, last_mouse_event.c);
  1069.     }
  1070.   else if (last_mouse_event.location == MOUSE_ON_INPUT)
  1071.     {
  1072.       goto_minibuffer ();
  1073. #ifdef HAVE_X11_X_H
  1074.       if (using_x)
  1075.     goto_char (io_col_to_input_pos (last_mouse_event.col));
  1076. #endif
  1077.     }
  1078.   else
  1079.     io_bell ();
  1080. }
  1081.  
  1082. #ifdef __STDC__
  1083. void
  1084. do_mouse_mark (void)
  1085. #else
  1086. void
  1087. do_mouse_mark ()
  1088. #endif
  1089. {
  1090.   if (last_mouse_event.location >= 0 && last_mouse_event.downp)
  1091.     {
  1092.       mkrow = last_mouse_event.r;
  1093.       mkcol = last_mouse_event.c;
  1094.     }
  1095. }
  1096.  
  1097.  
  1098. #ifdef __STDC__
  1099. void
  1100. do_mouse_mark_and_goto (void)
  1101. #else
  1102. void
  1103. do_mouse_mark_and_goto ()
  1104. #endif
  1105. {
  1106.   if (last_mouse_event.location >= 0 && last_mouse_event.downp)
  1107.     {
  1108.       mkrow = curow;
  1109.       mkcol = cucol;
  1110.     }
  1111.   do_mouse_goto ();
  1112. }
  1113.  
  1114. #ifdef __STDC__
  1115. void
  1116. do_mouse_cmd (void (*fn) ())
  1117. #else
  1118. void
  1119. do_mouse_cmd (fn)
  1120.      void (*fn) ();
  1121. #endif
  1122. {
  1123.   int seq = real_get_chr ();
  1124.   dequeue_mouse_event (&last_mouse_event, seq);
  1125.   fn ();
  1126. }
  1127.  
  1128. #ifdef __STDC__
  1129. void
  1130. mouse_mark_cmd (void)
  1131. #else
  1132. void
  1133. mouse_mark_cmd ()
  1134. #endif
  1135. {
  1136.   do_mouse_cmd (do_mouse_mark);
  1137. }
  1138.  
  1139.  
  1140. #ifdef __STDC__
  1141. void
  1142. mouse_goto_cmd (void)
  1143. #else
  1144. void
  1145. mouse_goto_cmd ()
  1146. #endif
  1147. {
  1148.   do_mouse_cmd (do_mouse_goto);
  1149. }
  1150.  
  1151. #ifdef __STDC__
  1152. void
  1153. mouse_mark_and_goto_cmd (void)
  1154. #else
  1155. void
  1156. mouse_mark_and_goto_cmd ()
  1157. #endif
  1158. {
  1159.   do_mouse_cmd (do_mouse_mark_and_goto);
  1160. }
  1161.  
  1162.  
  1163.  
  1164. /* Commands used to modify cell formulas. */
  1165.  
  1166. #ifdef __STDC__
  1167. void 
  1168. kill_cell_cmd (void)
  1169. #else
  1170. void 
  1171. kill_cell_cmd ()
  1172. #endif
  1173. {
  1174.   CELL *cp;
  1175.  
  1176.   cp = find_cell (curow, cucol);
  1177.   if (!cp)
  1178.     return;
  1179.   if ((GET_LCK (cp) == LCK_DEF && default_lock == LCK_LCK) || GET_LCK (cp) == LCK_LCK)
  1180.     {
  1181.       io_error_msg ("Cell %s is locked", cell_name (curow, cucol));
  1182.       return;
  1183.     }
  1184.   new_value (curow, cucol, "");
  1185.   cp->cell_flags = 0;
  1186.   cp->cell_font = 0;
  1187.   modified = 1;
  1188. }
  1189.  
  1190.  
  1191.  
  1192.  
  1193. /* A front end to sorting. */
  1194.  
  1195. #ifdef __STDC__
  1196. void
  1197. sort_region_cmd (char *ptr)
  1198. #else
  1199. void
  1200. sort_region_cmd (ptr)
  1201.      char *ptr;
  1202. #endif
  1203. {
  1204.   struct rng tmp_rng;
  1205.  
  1206.   if (get_abs_rng (&ptr, &sort_rng))
  1207.     {
  1208.       io_error_msg ("Can't find a range to sort in %s", ptr);
  1209.       return;
  1210.     }
  1211.  
  1212.   cur_row = sort_rng.lr;
  1213.   cur_col = sort_rng.lc;
  1214.  
  1215.   while (*ptr == ' ')
  1216.     ptr++;
  1217.   if (!*ptr)
  1218.     {
  1219.       sort_ele.lr = 0;
  1220.       sort_ele.lc = 0;
  1221.       sort_ele.hr = 0;
  1222.       sort_ele.hc = 0;
  1223.     }
  1224.   else if (!parse_cell_or_range (&ptr, &sort_ele))
  1225.     {
  1226.       io_error_msg ("Can't parse elements in %s", ptr);
  1227.       return;
  1228.     }
  1229.   else
  1230.     {
  1231.       sort_ele.lr -= sort_rng.lr;
  1232.       sort_ele.lc -= sort_rng.lc;
  1233.       sort_ele.hr -= sort_rng.lr;
  1234.       sort_ele.hc -= sort_rng.lc;
  1235.     }
  1236.  
  1237.   sort_keys_num = 0;
  1238.   while (*ptr == ' ')
  1239.     ptr++;
  1240.   for (; *ptr;)
  1241.     {
  1242.       if (sort_keys_num == sort_keys_alloc)
  1243.     {
  1244.       sort_keys_alloc++;
  1245.       if (sort_keys_alloc > 1)
  1246.         sort_keys = ck_realloc (sort_keys, sort_keys_alloc * sizeof (struct cmp));
  1247.       else
  1248.         sort_keys = ck_malloc (sizeof (struct cmp));
  1249.     }
  1250.       sort_keys[sort_keys_num].mult = 1;
  1251.       if (*ptr == '+')
  1252.     ptr++;
  1253.       else if (*ptr == '-')
  1254.     {
  1255.       sort_keys[sort_keys_num].mult = -1;
  1256.       ptr++;
  1257.     }
  1258.       if (!*ptr)
  1259.     {
  1260.       sort_keys[sort_keys_num].row = 0;
  1261.       sort_keys[sort_keys_num].col = 0;
  1262.       sort_keys_num++;
  1263.       break;
  1264.     }
  1265.       if (!parse_cell_or_range (&ptr, &tmp_rng) || tmp_rng.lr != tmp_rng.hr || tmp_rng.lc != tmp_rng.hc)
  1266.     {
  1267.       io_error_msg ("Can't parse key #%d in %s", sort_keys_num + 1, ptr);
  1268.       sort_keys_num = -1;
  1269.       return;
  1270.     }
  1271.       sort_keys[sort_keys_num].row = tmp_rng.lr - sort_rng.lr;
  1272.       sort_keys[sort_keys_num].col = tmp_rng.lc - sort_rng.lc;
  1273.       sort_keys_num++;
  1274.  
  1275.       while (*ptr == ' ')
  1276.     ptr++;
  1277.     }
  1278.   if (sort_keys_num == 0)
  1279.     {
  1280.       if (sort_keys_alloc == 0)
  1281.     {
  1282.       sort_keys_alloc++;
  1283.       sort_keys = ck_malloc (sizeof (struct cmp));
  1284.     }
  1285.       sort_keys[0].mult = 1;
  1286.       sort_keys[0].row = 0;
  1287.       sort_keys[0].col = 0;
  1288.       sort_keys_num++;
  1289.     }
  1290.   sort_region ();
  1291.   io_repaint ();
  1292. }
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298. #ifdef __STDC__
  1299. void
  1300. imove (struct rng * rng, int ch)
  1301. #else
  1302. void
  1303. imove (rng, ch)
  1304.      struct rng * rng;
  1305.      int ch;
  1306. #endif
  1307. {
  1308.   if ((ch > 0) && (ch != 27))
  1309.     pushed_back_char = ch;
  1310.  
  1311.   goto_region (rng);
  1312. }
  1313.  
  1314.  
  1315.  
  1316.  
  1317. /* Incremental navigation
  1318.  *
  1319.  * This should be called in edit mode while gathering arguments 
  1320.  * for a complex command.  The expected the_cmd_arg.
  1321.  */
  1322.  
  1323. #define MIN(A,B)    ((A) < (B) ? (A) : (B))
  1324.  
  1325. /* PAGE_RULE can be 0: page by  rows, 1: cols, 2 shorter of rows/cols,
  1326.  *               -1: don't page at all.
  1327.  */
  1328.  
  1329. #ifdef __STDC__
  1330. void
  1331. inc_direction (int count, int page_rule, int hack_magic)
  1332. #else
  1333. void
  1334. inc_direction (count, page_rule, hack_magic)
  1335.      int count;
  1336.      int page_rule;
  1337.      int hack_magic;
  1338. #endif
  1339. {
  1340.   if (check_editting_mode ())
  1341.     return;
  1342.  
  1343.   if (page_rule >= 0)
  1344.     {
  1345.       int page_size;
  1346.  
  1347.       switch (page_rule)
  1348.     {
  1349.     default:
  1350.     case 0:
  1351.       page_size = (cwin->screen.hr - cwin->screen.lr);
  1352.       break;
  1353.     case 1:
  1354.       page_size = (cwin->screen.hc - cwin->screen.lc);
  1355.       break;
  1356.     case 2:
  1357.       page_size = MIN ((cwin->screen.hr - cwin->screen.lr),
  1358.                (cwin->screen.hc - cwin->screen.lc));
  1359.       break;
  1360.     }
  1361.       count *= page_size;
  1362.     }
  1363.  
  1364.   if (the_cmd_frame->cmd && the_cmd_arg.inc_cmd)
  1365.     the_cmd_arg.inc_cmd (hack_magic, count);
  1366. }
  1367.  
  1368.  
  1369.  
  1370.  
  1371. /* The commands that move to the extreme of a row[col] may also move
  1372.  * forward or backward some number of col[row], according to the prefix
  1373.  * arg.  This is the logic of that.  This function returns the new col[row]
  1374.  * and operates on the presumption that MIN_ROW == MIN_COL and
  1375.  * MAX_ROW == MAX_COL.
  1376.  */
  1377.  
  1378. #ifdef __STDC__
  1379. static CELLREF
  1380. extreme_cmd_orth_motion (int count, CELLREF current)
  1381. #else
  1382. static CELLREF
  1383. extreme_cmd_orth_motion (count, current)
  1384.      int count;
  1385.      CELLREF current;
  1386. #endif
  1387. {
  1388.   --count;
  1389.   if (count > (MAX_ROW - current))
  1390.     count =  (MAX_ROW - current);
  1391.   else if (-count > (current - MIN_ROW))
  1392.     count = (MIN_ROW - current);
  1393.   return current + count;
  1394. }
  1395.  
  1396.  
  1397. #ifdef __STDC__
  1398. void
  1399. beginning_of_row (int count)
  1400. #else
  1401. void
  1402. beginning_of_row (count)
  1403.      int count;
  1404. #endif
  1405. {
  1406.   struct rng rng;
  1407.   rng.lr = extreme_cmd_orth_motion (count, curow);
  1408.   rng.lc = MIN_COL;
  1409.   rng.hr = mkrow;
  1410.   rng.hc = mkcol;
  1411.   goto_region (&rng);
  1412. }
  1413.  
  1414. #ifdef __STDC__
  1415. void
  1416. end_of_row (int count)
  1417. #else
  1418. void
  1419. end_of_row (count)
  1420.      int count;
  1421. #endif
  1422. {
  1423.   struct rng rng;
  1424.   rng.lr = extreme_cmd_orth_motion (count, curow);
  1425.   rng.lc = last_filled_col (rng.lr);
  1426.   rng.hr = mkrow;
  1427.   rng.hc = mkcol;
  1428.   goto_region (&rng);
  1429. }
  1430.  
  1431. #ifdef __STDC__
  1432. void
  1433. beginning_of_col (int count)
  1434. #else
  1435. void
  1436. beginning_of_col (count)
  1437.      int count;
  1438. #endif
  1439. {
  1440.   struct rng rng;
  1441.   rng.lr = MIN_ROW;
  1442.   rng.lc = extreme_cmd_orth_motion (count, cucol);
  1443.   rng.hr = mkrow;
  1444.   rng.hc = mkcol;
  1445.   goto_region (&rng);
  1446. }
  1447.  
  1448. #ifdef __STDC__
  1449. void
  1450. end_of_col (int count)
  1451. #else
  1452. void
  1453. end_of_col (count)
  1454.      int count;
  1455. #endif
  1456. {
  1457.   struct rng rng;
  1458.   rng.lc = extreme_cmd_orth_motion (count, cucol);
  1459.   rng.lr = last_filled_row (rng.lc);
  1460.   rng.hr = mkrow;
  1461.   rng.hc = mkcol;
  1462.   goto_region (&rng);
  1463. }
  1464.  
  1465.  
  1466. #ifdef __STDC__
  1467. static void
  1468. skip_empties (CELLREF * rout, CELLREF * cout, int magic)
  1469. #else
  1470. static void
  1471. skip_empties (rout, cout, magic)
  1472.      CELLREF * rout;
  1473.      CELLREF * cout;
  1474.      int magic;
  1475. #endif
  1476. {
  1477.   CELLREF r = *rout;
  1478.   CELLREF c = *cout;
  1479.   CELL * cp = find_cell (r, c);
  1480.  
  1481.   while (!cp || !GET_TYP (cp))
  1482.     {
  1483.       if (r != boundrymagic [rowmagic [magic] + 1])
  1484.     r += rowmagic [magic];
  1485.       else if (rowmagic [magic])
  1486.     break;
  1487.       if (c != boundrymagic [colmagic [magic] + 1])
  1488.     c += colmagic [magic];
  1489.       else if (colmagic[magic])
  1490.     break;
  1491.       cp = find_cell (r, c);
  1492.     }
  1493.  
  1494.   *rout = r;
  1495.   *cout = c;
  1496. }
  1497.  
  1498. #ifdef __STDC__
  1499. void
  1500. scan_cell_cursor (int magic, int count)
  1501. #else
  1502. void
  1503. scan_cell_cursor (magic, count)
  1504.      int magic;
  1505.      int count;
  1506. #endif
  1507. {
  1508.   CELLREF r = curow;
  1509.   CELLREF c = cucol;
  1510.   CELLREF last_r = r;
  1511.   CELLREF last_c = c;
  1512.  
  1513.   skip_empties (&r, &c, magic);
  1514.   {
  1515.     CELL * cp = find_cell (r, c);
  1516.     if (!(cp && GET_TYP (cp)))
  1517.       return;
  1518.   }
  1519.   while (count)
  1520.     {
  1521.       CELL * cp = find_cell (r, c);
  1522.       while (!cp || !GET_TYP (cp))
  1523.     {
  1524.       if (r != boundrymagic [rowmagic [magic] + 1])
  1525.         r += rowmagic [magic];
  1526.       else if (rowmagic [magic])
  1527.         break;
  1528.       if (c != boundrymagic [colmagic [magic] + 1])
  1529.         c += colmagic [magic];
  1530.       else if (colmagic[magic])
  1531.         break;
  1532.       cp = find_cell (r, c);
  1533.     }
  1534.       while (cp && GET_TYP (cp))
  1535.     {
  1536.       if (r != boundrymagic [rowmagic [magic] + 1])
  1537.         r += rowmagic [magic];
  1538.       else if (rowmagic[magic])
  1539.         break;
  1540.       if (c != boundrymagic [colmagic [magic] + 1])
  1541.         c += colmagic [magic];
  1542.       else if (colmagic [magic])
  1543.         break;
  1544.       last_r = r;
  1545.       last_c = c;
  1546.       cp = find_cell (r, c);
  1547.     }
  1548.       --count;
  1549.     }
  1550.   {
  1551.     struct rng rng;
  1552.     rng.lr = last_r;
  1553.     rng.lc = last_c;
  1554.     rng.hr = mkrow;
  1555.     rng.hc = mkcol;
  1556.     goto_region (&rng);
  1557.   }
  1558. }
  1559.  
  1560.  
  1561. #ifdef __STDC__
  1562. void
  1563. edit_cell (char * new_formula)
  1564. #else
  1565. void
  1566. edit_cell (new_formula)
  1567.      char * new_formula;
  1568. #endif
  1569. {
  1570.   char * fail;
  1571.   fail = new_value (setrow, setcol, new_formula);
  1572.   if (fail)
  1573.     io_error_msg (fail);
  1574.   else
  1575.     modified = 1;
  1576. }
  1577.  
  1578.  
  1579. #ifdef __STDC__
  1580. void
  1581. set_region_formula (struct rng * rng, char * str)
  1582. #else
  1583. void
  1584. set_region_formula (rng, str)
  1585.      struct rng * rng;
  1586.      char * str;
  1587. #endif
  1588. {
  1589.   CELLREF row, col;
  1590.  
  1591.   for (row = rng->lr; row <= rng->hr; ++row)
  1592.     for (col = rng->lc; col <= rng->hc; ++col)
  1593.       {
  1594.     char * error = new_value (row, col, str);
  1595.     if (!error)
  1596.       modified = 1;
  1597.     if (error)
  1598.       {
  1599.         io_error_msg (error);
  1600.         return;
  1601.       }
  1602.       }
  1603. }
  1604.  
  1605. #ifdef __STDC__
  1606. void
  1607. goto_edit_cell (int c)
  1608. #else
  1609. void
  1610. goto_edit_cell (c)
  1611.      int c;
  1612. #endif
  1613. {
  1614.   pushed_back_char = c;
  1615.   execute_command ("edit-cell", 1);
  1616. }
  1617.  
  1618.  
  1619. /* File i/o */
  1620.  
  1621. int sneaky_linec = 0;    /* for error reporting for now (see io-term.c) */
  1622.  
  1623. #ifdef __STDC__
  1624. void 
  1625. read_cmds_cmd (FILE *fp)
  1626. #else
  1627. void 
  1628. read_cmds_cmd (fp)
  1629.      FILE *fp;
  1630. #endif
  1631. {
  1632.   struct line line;
  1633.   char *ptr;
  1634.   init_line (&line);
  1635.   sneaky_linec = 0;
  1636.   while (read_line (&line, fp, &sneaky_linec))
  1637.     {
  1638.       for (ptr = line.buf; isspace (*ptr); ptr++);
  1639.       if (!*ptr || (*ptr == '#'))
  1640.     continue;
  1641.       execute_command (ptr, 1);
  1642.     }
  1643. }
  1644.  
  1645.  
  1646. static int run_load_hooks = 1;
  1647. static char load_hooks_string[] = "load_hooks";
  1648.  
  1649. #ifdef __STDC__
  1650. void
  1651. read_file_and_run_hooks (FILE * fp, int ismerge, char * name)
  1652. #else
  1653. void
  1654. read_file_and_run_hooks (fp, ismerge, name)
  1655.      FILE * fp;
  1656.      int ismerge;
  1657.      char * name;
  1658. #endif
  1659. {
  1660.   if (!ismerge)
  1661.     {
  1662.       if (current_filename)
  1663.     free (current_filename);
  1664.       current_filename = name ? ck_savestr (name) : 0;
  1665.     }
  1666.   (*read_file)(fp, ismerge);
  1667.   if (run_load_hooks)
  1668.     {
  1669.       struct var * v;
  1670.       v = find_var (load_hooks_string, sizeof (load_hooks_string) - 1);
  1671.       if (v && v->var_flags != VAR_UNDEF)
  1672.     execute_command (load_hooks_string, 1);
  1673.     }
  1674. }
  1675.  
  1676. /* If TURN_ON is 0, this toggles whether load hooks are run.
  1677.  * Otherwise, it turns load hooks on.
  1678.  */
  1679.  
  1680. #ifdef __STDC__
  1681. void
  1682. toggle_load_hooks (int turn_on)
  1683. #else
  1684. void
  1685. toggle_load_hooks (turn_on)
  1686.      int turn_on;
  1687. #endif
  1688. {
  1689.   if (!turn_on && run_load_hooks)
  1690.     {
  1691.       run_load_hooks = 0;
  1692.       io_info_msg ("load hooks turned off");
  1693.     }
  1694.   else
  1695.     {
  1696.       run_load_hooks = 1;
  1697.       io_info_msg ("load hooks turned on");
  1698.     }
  1699. }
  1700.  
  1701. #ifdef __STDC__
  1702. void
  1703. write_cmd (FILE *fp, char * name)
  1704. #else
  1705. void
  1706. write_cmd (fp, name)
  1707.      FILE *fp;
  1708.      char * name;
  1709. #endif
  1710. {
  1711.   if (current_filename)
  1712.     free (current_filename);
  1713.   current_filename = name ? ck_savestr (name) : 0;
  1714.   (*write_file) (fp, 0);
  1715.   modified = 0;
  1716. }
  1717.  
  1718. #ifdef __STDC__
  1719. void
  1720. read_cmd (FILE *fp, char * name)
  1721. #else
  1722. void
  1723. read_cmd (fp, name)
  1724.      FILE *fp;
  1725.      char * name;
  1726. #endif
  1727. {
  1728.   read_file_and_run_hooks (fp, 0, name);
  1729. }
  1730.  
  1731. #ifdef __STDC__
  1732. void
  1733. read_merge_cmd (FILE *fp)
  1734. #else
  1735. void
  1736. read_merge_cmd (fp)
  1737.      FILE *fp;
  1738. #endif
  1739. {
  1740.   (*read_file) (fp, 1);
  1741. }
  1742.  
  1743. #ifdef __STDC__
  1744. void
  1745. write_reg_cmd (FILE *fp, struct rng *rng)
  1746. #else
  1747. void
  1748. write_reg_cmd (fp, rng)
  1749.      FILE *fp;
  1750.      struct rng *rng;
  1751. #endif
  1752. {
  1753.   (*write_file) (fp, rng);
  1754. }
  1755.  
  1756.  
  1757.  
  1758.  
  1759. /* Cell attributes. */
  1760. #ifdef __STDC__
  1761. void
  1762. set_region_height (struct rng * rng, char * height)
  1763. #else
  1764. void
  1765. set_region_height (rng, height)
  1766.      struct rng * rng;
  1767.      char * height;
  1768. #endif
  1769. {
  1770.   int hgt;
  1771.   char * saved_height = height;
  1772.  
  1773.   while (isspace (*height))
  1774.     ++height;
  1775.  
  1776.   if (   !*height
  1777.       || words_imatch (&height, "d")
  1778.       || words_imatch (&height, "def")
  1779.       || words_imatch (&height, "default"))
  1780.     hgt = 0;
  1781.   else
  1782.     {
  1783.       hgt = astol (&height) + 1;
  1784.       if (hgt < 0)
  1785.         /* noreturn */
  1786.     io_error_msg ("Height (%d) can't be less than 0.", hgt);
  1787.     }      
  1788.  
  1789.   if (*height)
  1790.     {
  1791.       io_error_msg ("Unknown height '%s'", saved_height);
  1792.       /* Doesn't return */
  1793.     }
  1794.   {
  1795.     CELLREF cc;
  1796.     for (cc = rng->lr; ;cc++)
  1797.       {
  1798.     set_height (cc, hgt);
  1799.     if (cc == rng->hr)    /* This test goes here to prevent overflow. */
  1800.       break;
  1801.       }
  1802.     io_recenter_all_win ();
  1803.   }
  1804. }
  1805.  
  1806. #ifdef __STDC__
  1807. void
  1808. set_region_width (struct rng * rng, char * width)
  1809. #else
  1810. void
  1811. set_region_width (rng, width)
  1812.      struct rng * rng;
  1813.      char * width;
  1814. #endif
  1815. {
  1816.   char * saved_width = width;
  1817.   int wid;
  1818.  
  1819.   while (isspace (*width))
  1820.     ++width;
  1821.  
  1822.   if (   !*width
  1823.       || words_imatch (&width, "d")
  1824.       || words_imatch (&width, "def")
  1825.       || words_imatch (&width, "default"))
  1826.     wid = 0;
  1827.   else
  1828.     {
  1829.       wid = astol (&width) + 1;
  1830.       if (wid < 0)
  1831.         /* noreturn */
  1832.     io_error_msg ("Width (%d) can't be less than 0.", wid);
  1833.     }      
  1834.  
  1835.   if (*width)
  1836.     {
  1837.       io_error_msg ("Unknown width '%s'", saved_width);
  1838.       /* No return. */
  1839.     }
  1840.   {
  1841.     CELLREF cc;
  1842.     for (cc = rng->lc; ;cc++)
  1843.       {
  1844.     set_width (cc, wid);
  1845.     if (cc == rng->hc)    /* This test goes here to prevent overflow. */
  1846.       break;
  1847.       }
  1848.     io_recenter_all_win ();
  1849.   }
  1850. }
  1851.  
  1852.  
  1853. /* PROT may be `d', `p', or `u'. */
  1854.  
  1855. #ifdef __STDC__
  1856. void
  1857. set_region_protection (struct rng * rng, int prot)
  1858. #else
  1859. void
  1860. set_region_protection (rng, prot)
  1861.      struct rng * rng;
  1862.      int prot;
  1863. #endif
  1864. {
  1865.   prot = tolower (prot);
  1866.   switch (prot)
  1867.     {
  1868.     case 'd':
  1869.       lock_region (rng, LCK_DEF);
  1870.       break;
  1871.     case 'p':
  1872.       lock_region (rng, LCK_LCK);
  1873.       break;
  1874.     case 'u':
  1875.       lock_region (rng, LCK_UNL);
  1876.       break;
  1877.     default:
  1878.       io_error_msg ("Bad argument to protect-region %c.", prot);
  1879.       break;
  1880.     }
  1881. }
  1882.  
  1883. #ifdef __STDC__
  1884. void
  1885. set_region_alignment (struct rng * rng, int align)
  1886. #else
  1887. void
  1888. set_region_alignment (rng, align)
  1889.      struct rng * rng;
  1890.      int align;
  1891. #endif
  1892. {
  1893.   int fun = chr_to_jst (align);
  1894.   if (fun != -1)
  1895.     format_region (rng, -1, fun);
  1896.   else            /* if (main_map[align]!=BREAK_CMD) */
  1897.     io_error_msg ("Unknown Justify '%s'", char_to_string (align));
  1898. }
  1899.  
  1900. #ifdef __STDC__
  1901. void
  1902. set_region_format (struct rng * rng, int fmt)
  1903. #else
  1904. void
  1905. set_region_format (rng, fmt)
  1906.      struct rng * rng;
  1907.      int fmt;
  1908. #endif
  1909. {
  1910.   format_region (rng, fmt, -1); 
  1911. }
  1912.  
  1913.  
  1914.  
  1915.  
  1916. #ifdef __STDC__
  1917. void
  1918. set_def_height (char * height)
  1919. #else
  1920. void
  1921. set_def_height (height)
  1922.      char * height;
  1923. #endif
  1924. {
  1925.   char * saved_height = height;
  1926.   int hgt;
  1927.  
  1928.   while (isspace (*height))
  1929.     ++height;
  1930.  
  1931.   if (   !*height
  1932.       || words_imatch (&height, "d")
  1933.       || words_imatch (&height, "def")
  1934.       || words_imatch (&height, "default"))
  1935.     hgt = 0;
  1936.   else
  1937.     {
  1938.       hgt = astol (&height);
  1939.       if (hgt < 0)
  1940.         /* noreturn */
  1941.     io_error_msg ("Height (%d) can't be less than 0.", hgt);
  1942.     }      
  1943.  
  1944.   if (*height)
  1945.     {
  1946.       io_error_msg ("Unknown height '%s'", saved_height);
  1947.       /* No return. */
  1948.     }
  1949.   default_height = hgt;
  1950.   io_recenter_all_win ();
  1951. }
  1952.  
  1953. #ifdef __STDC__
  1954. void
  1955. set_def_width (char * width)
  1956. #else
  1957. void
  1958. set_def_width (width)
  1959.      char * width;
  1960. #endif
  1961. {
  1962.   char * saved_width = width;
  1963.   int wid;
  1964.  
  1965.   while (isspace (*width))
  1966.     ++width;
  1967.  
  1968.   if (   !*width
  1969.       || words_imatch (&width, "d")
  1970.       || words_imatch (&width, "def")
  1971.       || words_imatch (&width, "default"))
  1972.     wid = 8;
  1973.   else
  1974.     {
  1975.       wid = astol (&width);
  1976.       if (wid < 0)
  1977.         /* noreturn */
  1978.     io_error_msg ("Width (%d) can't be less than 0.", wid);
  1979.     }      
  1980.  
  1981.   if (*width)
  1982.     {
  1983.       io_error_msg ("Unknown width '%s'", saved_width);
  1984.       /* No return. */
  1985.     }
  1986.   default_width = wid;
  1987.   io_recenter_all_win ();
  1988. }
  1989.  
  1990. /* PROT may be `d', `p', or `u'. */
  1991.  
  1992. #ifdef __STDC__
  1993. void
  1994. set_def_protection (int prot)
  1995. #else
  1996. void
  1997. set_def_protection (prot)
  1998.      int prot;
  1999. #endif
  2000. {
  2001.   prot = tolower (prot);
  2002.   switch (prot)
  2003.     {
  2004.     case 'p':
  2005.       default_lock = LCK_LCK;
  2006.       break;
  2007.     case 'u':
  2008.       default_lock = LCK_UNL;
  2009.       break;
  2010.     default:
  2011.       io_error_msg ("Bad argument to set-default-protection %c.", prot);
  2012.       break;
  2013.     }
  2014. }
  2015.  
  2016. #ifdef __STDC__
  2017. void
  2018. set_def_alignment (int align)
  2019. #else
  2020. void
  2021. set_def_alignment (align)
  2022.      int align;
  2023. #endif
  2024. {
  2025.   int fun = chr_to_jst (align);
  2026.   if (fun == -1)
  2027.     io_error_msg ("Unknown justification.");
  2028.  
  2029.   default_jst = fun;
  2030.   io_repaint ();
  2031. }
  2032.  
  2033. #ifdef __STDC__
  2034. void
  2035. set_def_format (int fmt)
  2036. #else
  2037. void
  2038. set_def_format (fmt)
  2039.      int fmt;
  2040. #endif
  2041. {
  2042.   default_fmt = fmt;
  2043.   io_repaint ();
  2044. }
  2045.  
  2046.  
  2047.  
  2048. #ifdef __STDC__
  2049. void
  2050. define_usr_fmt (int fmt, char * pos_h, char * neg_h, char * pos_t,
  2051.         char * neg_t, char * zero, char * comma, char * decimal,
  2052.         char * precision, char * scale)
  2053. #else
  2054. void
  2055. define_usr_fmt (fmt, pos_h, neg_h, pos_t, neg_t, zero,
  2056.         comma, decimal, precision, scale)
  2057.      int fmt;
  2058.      char * pos_h;
  2059.      char * neg_h;
  2060.      char * pos_t;
  2061.      char * neg_t;
  2062.      char * zero;
  2063.      char * comma;
  2064.      char * decimal;
  2065.      char * precision;
  2066.      char * scale;
  2067. #endif
  2068. {
  2069.   char * usr_buf[9];
  2070.   if (fmt < 1 || fmt > 16)
  2071.     {
  2072.       io_error_msg ("Format number out of range %d (should be in [1..16].",
  2073.             fmt);
  2074.       /* no return */
  2075.     }
  2076.   /* Vector to an older interface... */
  2077.   --fmt;
  2078.   usr_buf[0] = pos_h;
  2079.   usr_buf[1] = neg_h;
  2080.   usr_buf[2] = pos_t;
  2081.   usr_buf[3] = neg_t;
  2082.   usr_buf[4] = zero;
  2083.   usr_buf[5] = comma;
  2084.   usr_buf[6] = decimal;
  2085.   usr_buf[7] = precision;
  2086.   usr_buf[8] = scale;
  2087.   set_usr_stats (fmt, usr_buf);
  2088. }
  2089.  
  2090.  
  2091.  
  2092. /* Automatic motion while editting cell's: */
  2093.  
  2094. /* Hmm... where should this variable *really* go? */
  2095.  
  2096. static int auto_motion_direction = magic_down;
  2097.  
  2098. #ifdef __STDC__
  2099. void
  2100. set_auto_direction (enum motion_magic magic)
  2101. #else
  2102. void
  2103. set_auto_direction (magic)
  2104.      enum motion_magic magic;
  2105. #endif
  2106. {
  2107.   auto_motion_direction = magic;
  2108.   io_info_msg ("Auto-motion direction = %s.", motion_name[magic]);
  2109. }
  2110.  
  2111. #ifdef __STDC__
  2112. void
  2113. auto_move (void)
  2114. #else
  2115. void
  2116. auto_move ()
  2117. #endif
  2118. {
  2119.   shift_cell_cursor (auto_motion_direction, 1);
  2120. }
  2121.  
  2122. #ifdef __STDC__
  2123. void
  2124. auto_next_set (void)
  2125. #else
  2126. void
  2127. auto_next_set ()
  2128. #endif
  2129. {
  2130.   scan_cell_cursor (opposite_motion[auto_motion_direction], 1);
  2131.   shift_cell_cursor (complementary_motion[auto_motion_direction], 1);
  2132. }
  2133.  
  2134.  
  2135. /* This decompiles and then recompiles all of the formulas of cells.
  2136.  * This is never normally necessary unless you happen to have some
  2137.  * spreadsheets written when the byte-code compiler had bugs that
  2138.  * made your formulas produce parse errors.
  2139.  */
  2140.  
  2141. #ifdef __STDC__
  2142. void
  2143. recompile_spreadsheet (void)
  2144. #else
  2145. void
  2146. recompile_spreadsheet ()
  2147. #endif
  2148. {
  2149.   struct rng rng;
  2150.   CELL * cp;
  2151.   CELLREF r;
  2152.   CELLREF c;
  2153.   rng.lr = MIN_ROW;
  2154.   rng.lc = MIN_COL;
  2155.   rng.hr = MAX_ROW;
  2156.   rng.hc = MAX_COL;
  2157.   find_cells_in_range (&rng);
  2158.   for (cp = next_row_col_in_range (&r, &c);
  2159.        cp;
  2160.        cp = next_row_col_in_range(&r, &c))
  2161.     {
  2162.       char * form = decomp (r, c, cp);
  2163.       set_cell (r, c, form);
  2164.       if (my_cell)
  2165.     {
  2166.       update_cell (my_cell);
  2167.       if (is_constant (my_cell->cell_formula))
  2168.         {
  2169.           byte_free (my_cell->cell_formula);
  2170.           my_cell->cell_formula = 0;
  2171.         }
  2172.       io_pr_cell (r, c, my_cell);
  2173.       my_cell = 0;
  2174.     }
  2175.       decomp_free ();
  2176.     }
  2177. }
  2178.  
  2179.